package com.andova.camera.glsurface

import android.content.Context
import android.opengl.GLES20
import android.opengl.GLES30
import android.util.AttributeSet
import com.andova.ext.i
import com.andova.image.glesInitialize
import java.io.InputStream
import java.nio.ByteBuffer
import java.nio.ByteOrder
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

@Deprecated("", ReplaceWith("CameraGLSurfaceView"))
class GLCameraSurfaceViewWithBuffer(context: Context, attrs: AttributeSet?) : GLCameraSurfaceView(context, attrs) {
    private var texIdY = -1
    private var texIdUV = -1

    constructor(context: Context) : this(context, null)

    init {
        setEGLContextClientVersion(3)
        setRenderer(this)
        renderMode = RENDERMODE_CONTINUOUSLY // todo RENDERMODE_WHEN_DIRTY
    }

    private fun getInstr(instr: InputStream): String = String(instr.readBytes())
    override fun onRelease() = release()
    override fun glDrawFrame(gl: GL10?) { // todo camera release
        if (bufferUpdated()) {
            GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
            GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, texIdY)
            GLES30.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, getPreviewWidth(), getPreviewHeight(), 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, getBufferY()?.position(0))
            GLES30.glActiveTexture(GLES30.GL_TEXTURE1)
            GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, texIdUV)
            GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_LUMINANCE_ALPHA, getPreviewWidth() / 2, getPreviewHeight() / 2, 0, GLES30.GL_LUMINANCE_ALPHA, GLES30.GL_UNSIGNED_BYTE, getBufferUV()?.position(0))
            bufferUpdated(false) // todo synchronized
        }
        GLES30.glEnableVertexAttribArray(1)
        GLES30.glEnableVertexAttribArray(2)
        val vertex = floatArrayOf(
                -1f, -1f,
                1f, -1f,
                -1f, 1f,
                1f, 1f
        )
        val texture = floatArrayOf(
                0f, 1f,
                1f, 1f,
                0f, 0f,
                1f, 0f
        )
        val vertexBuffer = ByteBuffer.allocateDirect(vertex.size * 4).order(ByteOrder.nativeOrder()).asFloatBuffer()
        vertexBuffer.put(vertex)
        vertexBuffer.position(0)
        val textureBuffer = ByteBuffer.allocateDirect(texture.size * 4).order(ByteOrder.nativeOrder()).asFloatBuffer()
        textureBuffer.put(texture)
        textureBuffer.position(0)
        GLES30.glVertexAttribPointer(1, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer)
        GLES30.glVertexAttribPointer(2, 2, GLES20.GL_FLOAT, false, 0, textureBuffer)
        GLES30.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4)
    }

    override fun glSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        val preW = getPreviewWidth()
        val preH = getPreviewHeight()
        i("surfaceWidth:$width, surfaceHeight:$height, previewWidth:$preW, previewHeight:$preH")
        if (width < height) { // 竖屏
            if (preW < preH) {
                GLES30.glViewport(0, 0, width, height / width / height)
            } else {
                GLES30.glViewport(0, 0, width, (width / preW.toFloat() * preH).toInt())
            }
        } else {

        }
//        GLES30.glViewport(0, 0, width, height)
    }

    override fun lazyCallback(millis: Long) {
        TODO("Not yet implemented")
    }

    override fun glSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        openCamera(true)
        GLES30.glClearColor(1f, 1f, 1f, 1f)
        val program = glesInitialize(getInstr(context.assets.open("v_texture_yuv.glsl")), getInstr(context.assets.open("f_texture_yuv.glsl")))
        GLES30.glUseProgram(program)
        val texIdArray = IntArray(2)
        GLES30.glGenTextures(2, texIdArray, 0)
        texIdY = texIdArray[0]
        texIdUV = texIdArray[1]
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, texIdY)
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST)
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, texIdUV)
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST)
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)

        GLES30.glUniform1i(GLES30.glGetUniformLocation(program, "u_TextureUV"), 1) // 这里的参数1对应GL_TEXTURE1
    }
}